using System;
using System.Collections.Generic;
using CodePlex.TfsLibrary.ObjectModel;
using CodePlex.TfsLibrary.RepositoryWebSvc;
using CodePlex.UnitTestUtility;
using Xunit;

namespace CodePlex.TfsLibrary.ClientEngine
{
    public class TfsEngineDeleteTest
    {
        public class Delete
        {
            [Fact]
            public void ItemNotTrackedAndNotPresent()
            {
                SourceItem callbackItem = null;
                SourceItemResult callbackResult = SourceItemResult.S_Ok;
                TestableTfsEngine engine = TestableTfsEngine.Create();

                engine.Delete(@"C:\Biff.txt", false, delegate(SourceItem item,
                                                              SourceItemResult result)
                                                     {
                                                         callbackItem = item;
                                                         callbackResult = result;
                                                     });

                Assert.Equal(@"C:\Biff.txt", callbackItem.LocalName);
                Assert.Equal(SourceItemResult.E_PathNotFound, callbackResult);
            }

            [Fact]
            public void NullPath()
            {
                TestableTfsEngine engine = TestableTfsEngine.Create();

                Assert.Throws<ArgumentNullException>(delegate
                                                     {
                                                         engine.Delete(null, false, null);
                                                     });
            }
        }

        public class Delete_File
        {
            [Fact]
            public void VerifiesDirectoryStructure()
            {
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.WriteAllText(@"C:\Foo\bar.txt", "Text");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFile(@"C:\Foo\bar.txt", 1, 2, SourceItemStatus.Unmodified);

                engine.Delete(@"C:\Foo\bar.txt", false, null);

                Assert.Equal(@"C:\Foo", engine.ValidateDirectoryStructure_Directory);
            }
        }

        public class Delete_File_NotTracked
        {
            [Fact]
            public void Forced()
            {
                SourceItem callbackItem = null;
                SourceItemResult callbackResult = SourceItemResult.S_Ok;
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.WriteAllText(@"C:\Foo\bar.txt", "Text");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);

                engine.Delete(@"C:\Foo\bar.txt", true, delegate(SourceItem item,
                                                                SourceItemResult result)
                                                       {
                                                           callbackItem = item;
                                                           callbackResult = result;
                                                       });

                Assert.Equal(@"C:\Foo\bar.txt", callbackItem.LocalName);
                Assert.Equal(SourceItemResult.S_ForcedDelete, callbackResult);
                Assert.False(engine.FileSystem.FileExists(@"C:\Foo\bar.txt"));
            }

            [Fact]
            public void NotForced()
            {
                SourceItem callbackItem = null;
                SourceItemResult callbackResult = SourceItemResult.S_Ok;
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.WriteAllText(@"C:\Foo\bar.txt", "Text");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);

                engine.Delete(@"C:\Foo\bar.txt", false, delegate(SourceItem item,
                                                                 SourceItemResult result)
                                                        {
                                                            callbackItem = item;
                                                            callbackResult = result;
                                                        });

                Assert.Equal(@"C:\Foo\bar.txt", callbackItem.LocalName);
                Assert.Equal(SourceItemResult.E_NotUnderSourceControl, callbackResult);
                Assert.True(engine.FileSystem.FileExists(@"C:\Foo\bar.txt"));
            }

            [Fact]
            public void ParentFolderNotTracked()
            {
                SourceItem callbackItem = null;
                SourceItemResult callbackResult = SourceItemResult.S_Ok;
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.WriteAllText(@"C:\Foo\bar.txt", "Text");

                engine.Delete(@"C:\Foo\bar.txt", false, delegate(SourceItem item,
                                                                 SourceItemResult result)
                                                        {
                                                            callbackItem = item;
                                                            callbackResult = result;
                                                        });

                Assert.Equal(@"C:\Foo\bar.txt", callbackItem.LocalName);
                Assert.Equal(SourceItemResult.E_NotInAWorkingFolder, callbackResult);
            }
        }

        public class Delete_File_Tracked
        {
            [Fact]
            public void Added()
            {
                SourceItem callbackItem = null;
                SourceItemResult callbackResult = SourceItemResult.S_Ok;
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.WriteAllText(@"C:\Foo\bar.txt", "Text");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFile(@"C:\Foo\bar.txt", 1, 2, SourceItemStatus.Add);

                engine.Delete(@"C:\Foo\bar.txt", false, delegate(SourceItem item,
                                                                 SourceItemResult result)
                                                        {
                                                            callbackItem = item;
                                                            callbackResult = result;
                                                        });

                Assert.Equal(@"C:\Foo\bar.txt", callbackItem.LocalName);
                Assert.Equal(SourceItemResult.E_HasLocalModifications, callbackResult);
            }

            [Fact]
            public void Added_Forced()
            {
                bool callbackCalled = false;
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.WriteAllText(@"C:\Foo\bar.txt", "Text");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFile(@"C:\Foo\bar.txt", 1, 2, SourceItemStatus.Add);

                engine.Delete(@"C:\Foo\bar.txt", true, delegate
                                                       {
                                                           callbackCalled = true;
                                                       });

                Assert.True(callbackCalled);
                Assert.False(engine.TfsState.IsFileTracked(@"C:\Foo\bar.txt"));
                Assert.False(engine.FileSystem.FileExists(@"C:\Foo\bar.txt"));
            }

            [Fact]
            public void Deleted()
            {
                bool callbackCalled = false;
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFile(@"C:\Foo\bar.txt", 1, 2, SourceItemStatus.Delete);

                engine.Delete(@"C:\Foo\bar.txt", false, delegate
                                                        {
                                                            callbackCalled = true;
                                                        });

                Assert.True(callbackCalled);
            }

            [Fact]
            public void Missing()
            {
                bool callbackCalled = false;
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.WriteAllText(@"C:\Foo\bar.txt", "Text");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFile(@"C:\Foo\bar.txt", 1, 2, SourceItemStatus.Unmodified);
                engine.FileSystem.DeleteFile(@"C:\Foo\bar.txt");

                engine.Delete(@"C:\Foo\bar.txt", false, delegate
                                                        {
                                                            callbackCalled = true;
                                                        });

                Assert.False(engine.FileSystem.FileExists(@"C:\Foo\bar.txt"));
                Assert.True(callbackCalled);
                Assert.Equal(SourceItemStatus.Delete, engine.GetSourceItem(@"C:\Foo\bar.txt").LocalItemStatus);
            }

            [Fact]
            public void Modified()
            {
                SourceItem callbackItem = null;
                SourceItemResult callbackResult = SourceItemResult.S_Ok;
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.WriteAllText(@"C:\Foo\bar.txt", "Text");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFile(@"C:\Foo\bar.txt", 1, 2, SourceItemStatus.Unmodified);
                engine.FileSystem.WriteAllText(@"C:\Foo\bar.txt", "New Text");

                engine.Delete(@"C:\Foo\bar.txt", false, delegate(SourceItem item,
                                                                 SourceItemResult result)
                                                        {
                                                            callbackItem = item;
                                                            callbackResult = result;
                                                        });

                Assert.Equal(@"C:\Foo\bar.txt", callbackItem.LocalName);
                Assert.Equal(SourceItemResult.E_HasLocalModifications, callbackResult);
                Assert.True(engine.FileSystem.FileExists(@"C:\Foo\bar.txt"));
            }

            [Fact]
            public void Modified_Forced()
            {
                SourceItem callbackItem = null;
                SourceItemResult callbackResult = SourceItemResult.S_Ok;
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.WriteAllText(@"C:\Foo\bar.txt", "Text");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFile(@"C:\Foo\bar.txt", 1, 2, SourceItemStatus.Unmodified);
                engine.FileSystem.WriteAllText(@"C:\Foo\bar.txt", "New Text");

                engine.Delete(@"C:\Foo\bar.txt", true, delegate(SourceItem item,
                                                                SourceItemResult result)
                                                       {
                                                           callbackItem = item;
                                                           callbackResult = result;
                                                       });

                Assert.Equal(@"C:\Foo\bar.txt", callbackItem.LocalName);
                Assert.Equal(SourceItemResult.S_ForcedDelete, callbackResult);
                Assert.True(engine.TfsState.IsFileTracked(@"C:\Foo\bar.txt"));
                Assert.False(engine.FileSystem.FileExists(@"C:\Foo\bar.txt"));
            }

            [Fact]
            public void Unmodified()
            {
                SourceItem callbackItem = null;
                SourceItemResult callbackResult = SourceItemResult.S_Ok;
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.WriteAllText(@"C:\Foo\bar.txt", "Text");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFile(@"C:\Foo\bar.txt", 1, 2, SourceItemStatus.Unmodified);

                engine.Delete(@"C:\Foo\bar.txt", false, delegate(SourceItem item,
                                                                 SourceItemResult result)
                                                        {
                                                            callbackItem = item;
                                                            callbackResult = result;
                                                        });

                Assert.Equal(1, callbackItem.ItemId);
                Assert.Equal(ItemType.File, callbackItem.ItemType);
                Assert.Equal(2, callbackItem.LocalChangesetId);
                Assert.Equal(SourceItemStatus.Delete, callbackItem.LocalItemStatus);
                Assert.Equal(@"C:\Foo\bar.txt", callbackItem.LocalName);
                Assert.Equal(SourceItemResult.S_Ok, callbackResult);

                SourceItem resultItem = engine.TfsState.GetSourceItem(@"C:\Foo\bar.txt");
                Assert.Equal(1, resultItem.ItemId);
                Assert.Equal(ItemType.File, resultItem.ItemType);
                Assert.Equal(2, resultItem.LocalChangesetId);
                Assert.Equal(SourceItemStatus.Delete, resultItem.LocalItemStatus);
                Assert.Equal(@"C:\Foo\bar.txt", resultItem.LocalName);

                Assert.False(engine.FileSystem.FileExists(@"C:\Foo\bar.txt"));
            }
        }

        public class Delete_Folder
        {
            [Fact]
            public void VerifiesDirectoryStructure()
            {
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar", @"C:\Foo\Bar", 0, 0, SourceItemStatus.Unmodified);

                engine.Delete(@"C:\Foo\Bar", false, null);

                Assert.Equal(@"C:\Foo", engine.ValidateDirectoryStructure_Directory);
            }
        }

        public class Delete_Folder_NotTracked
        {
            [Fact]
            public void Forced()
            {
                SourceItem callbackItem = null;
                SourceItemResult callbackResult = SourceItemResult.S_Ok;
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Biff");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);

                engine.Delete(@"C:\Foo\Biff", true, delegate(SourceItem item,
                                                             SourceItemResult result)
                                                    {
                                                        callbackItem = item;
                                                        callbackResult = result;
                                                    });

                Assert.False(engine.FileSystem.DirectoryExists(@"C:\Foo\Biff"));
                Assert.Equal(@"C:\Foo\Biff", callbackItem.LocalName);
                Assert.Equal(SourceItemResult.S_ForcedDelete, callbackResult);
            }

            [Fact]
            public void Forced_Recursive()
            {
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar\Baz");
                engine.FileSystem.WriteAllText(@"C:\Foo\Bar\bar.txt", "text");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);

                engine.Delete(@"C:\Foo\Bar", true, null);

                Assert.False(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar\Baz"));
                Assert.False(engine.FileSystem.FileExists(@"C:\Foo\Bar\bar.txt"));
                Assert.False(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar"));
            }

            [Fact]
            public void NotForced()
            {
                SourceItem callbackItem = null;
                SourceItemResult callbackResult = SourceItemResult.S_Ok;
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Biff");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);

                engine.Delete(@"C:\Foo\Biff", false, delegate(SourceItem item,
                                                              SourceItemResult result)
                                                     {
                                                         callbackItem = item;
                                                         callbackResult = result;
                                                     });

                Assert.True(engine.FileSystem.DirectoryExists(@"C:\Foo\Biff"));
                Assert.Equal(@"C:\Foo\Biff", callbackItem.LocalName);
                Assert.Equal(SourceItemResult.E_NotUnderSourceControl, callbackResult);
            }

            [Fact]
            public void ParentFolderNotTracked()
            {
                SourceItem callbackItem = null;
                SourceItemResult callbackResult = SourceItemResult.S_Ok;
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar");

                engine.Delete(@"C:\Foo\Bar", false, delegate(SourceItem item,
                                                             SourceItemResult result)
                                                    {
                                                        callbackItem = item;
                                                        callbackResult = result;
                                                    });

                Assert.Equal(@"C:\Foo\Bar", callbackItem.LocalName);
                Assert.Equal(SourceItemResult.E_NotInAWorkingFolder, callbackResult);
            }
        }

        public class Delete_Folder_Tracked
        {
            [Fact]
            public void Added()
            {
                SourceItem callbackItem = null;
                SourceItemResult callbackResult = SourceItemResult.S_Ok;
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar/", @"C:\Foo\Bar", 0, 0, SourceItemStatus.Add);

                engine.Delete(@"C:\Foo\Bar", false, delegate(SourceItem item,
                                                             SourceItemResult result)
                                                    {
                                                        callbackItem = item;
                                                        callbackResult = result;
                                                    });

                Assert.Equal(@"C:\Foo\Bar", callbackItem.LocalName);
                Assert.Equal(SourceItemResult.E_HasLocalModifications, callbackResult);
            }

            [Fact]
            public void Added_Forced()
            {
                SourceItem callbackItem = null;
                SourceItemResult callbackResult = SourceItemResult.S_Ok;
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Biff");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Biff/", @"C:\Foo\Biff", 0, 0, SourceItemStatus.Add);

                engine.Delete(@"C:\Foo\Biff", true, delegate(SourceItem item,
                                                             SourceItemResult result)
                                                    {
                                                        callbackItem = item;
                                                        callbackResult = result;
                                                    });

                Assert.Equal(@"C:\Foo\Biff", callbackItem.LocalName);
                Assert.Equal(SourceItemResult.S_Ok, callbackResult);
                Assert.False(engine.TfsState.IsFolderTracked(@"C:\Foo\Biff"));
                Assert.False(engine.FileSystem.DirectoryExists(@"C:\Foo\Biff"));

                foreach (TfsStateEntry entry in engine.TfsState.GetItems(@"C:\Foo"))
                    Assert.NotEqual(entry.Name, "Biff");
            }

            [Fact]
            public void Deleted()
            {
                bool callbackCalled = false;
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar/", @"C:\Foo\Bar", 0, 0, SourceItemStatus.Delete);

                engine.Delete(@"C:\Foo\Bar", false, delegate
                                                    {
                                                        callbackCalled = true;
                                                    });

                Assert.True(callbackCalled);
            }

            [Fact]
            public void Missing()
            {
                SourceItem callbackItem = null;
                SourceItemResult callbackResult = SourceItemResult.S_Ok;
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/", @"C:\Foo\Bar", 0, 0, SourceItemStatus.Unmodified);
                engine.FileSystem.DeleteDirectory(@"C:\Foo\Bar", true);

                engine.Delete(@"C:\Foo\Bar", false, delegate(SourceItem item,
                                                             SourceItemResult result)
                                                    {
                                                        callbackItem = item;
                                                        callbackResult = result;
                                                    });

                Assert.Equal(@"C:\Foo\Bar", callbackItem.LocalName);
                Assert.Equal(SourceItemResult.S_Ok, callbackResult);
            }

            [Fact]
            public void Missing_RecursionUsesShadowEntries()
            {
                List<SourceItemCallbackData> results = new List<SourceItemCallbackData>();
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar\Baz");
                engine.FileSystem.WriteAllText(@"C:\Foo\Bar\Baz\biff.txt", "some text");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/", @"C:\Foo\Bar", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/", @"C:\Foo\Bar\Baz", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFile(@"C:\Foo\Bar\Baz\biff.txt", 0, 0, SourceItemStatus.Unmodified);
                engine.FileSystem.DeleteDirectory(@"C:\Foo\Bar", true);

                engine.Delete(@"C:\Foo\Bar", false,
                              delegate(SourceItem item,
                                       SourceItemResult result)
                              {
                                  results.Add(new SourceItemCallbackData(item, result));
                              });

                Assert.Equal(3, results.Count);
                Assert.Equal(@"C:\Foo\Bar\Baz\biff.txt", results[0].SourceItem.LocalName);
                Assert.Equal(SourceItemResult.S_Ok, results[0].SourceItemResult);
                Assert.Equal(@"C:\Foo\Bar\Baz", results[1].SourceItem.LocalName);
                Assert.Equal(SourceItemResult.S_Ok, results[1].SourceItemResult);
                Assert.Equal(@"C:\Foo\Bar", results[2].SourceItem.LocalName);
                Assert.Equal(SourceItemResult.S_Ok, results[2].SourceItemResult);
            }

            [Fact]
            public void Unmodified()
            {
                SourceItem callbackItem = null;
                SourceItemResult callbackResult = SourceItemResult.S_Ok;
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/Foo", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/Foo/Bar", @"C:\Foo\Bar", 0, 0, SourceItemStatus.Unmodified);

                engine.Delete(@"C:\Foo\Bar", false, delegate(SourceItem item,
                                                             SourceItemResult result)
                                                    {
                                                        callbackItem = item;
                                                        callbackResult = result;
                                                    });

                Assert.True(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar"));
                Assert.Equal(Constants.NullItemId, callbackItem.ItemId);
                Assert.Equal(ItemType.Folder, callbackItem.ItemType);
                Assert.Equal(Constants.NullChangesetId, callbackItem.LocalChangesetId);
                Assert.Equal(SourceItemStatus.Delete, callbackItem.LocalItemStatus);
                Assert.Equal(@"C:\Foo\Bar", callbackItem.LocalName);
                Assert.Equal(SourceItemResult.S_Ok, callbackResult);
            }
        }

        public class Delete_Recursion
        {
            [Fact]
            public void DeepNesting_AllUnmodified()
            {
                int deleteCallbackCount = 0;
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar");
                engine.FileSystem.WriteAllText(@"C:\Foo\Bar\biff.txt", "Biff!");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar\Baz1");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar\Baz1\Fibble");
                engine.FileSystem.WriteAllText(@"C:\Foo\Bar\Baz1\hello.txt", "Hello...");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar\Baz2");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar\Baz3");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar", @"C:\Foo\Bar", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFile(@"C:\Foo\Bar\biff.txt", 1, 2, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar/Baz1", @"C:\Foo\Bar\Baz1", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar/Baz1/Fibble", @"C:\Foo\Bar\Baz1\Fibble", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFile(@"C:\Foo\Bar\Baz1\hello.txt", 3, 4, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar/Baz2", @"C:\Foo\Bar\Baz2", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar/Baz3", @"C:\Foo\Bar\Baz3", 0, 0, SourceItemStatus.Unmodified);

                engine.Delete(@"C:\Foo\Bar", false, delegate(SourceItem item,
                                                             SourceItemResult result)
                                                    {
                                                        Assert.Equal(SourceItemResult.S_Ok, result);
                                                        ++deleteCallbackCount;
                                                    });

                Assert.Equal(7, deleteCallbackCount);

                Assert.Equal(SourceItemStatus.Delete, engine.TfsState.GetSourceItem(@"C:\Foo\Bar").LocalItemStatus);
                Assert.Equal(SourceItemStatus.Delete, engine.TfsState.GetSourceItem(@"C:\Foo\Bar\biff.txt").LocalItemStatus);
                Assert.Equal(SourceItemStatus.Delete, engine.TfsState.GetSourceItem(@"C:\Foo\Bar\Baz1").LocalItemStatus);
                Assert.Equal(SourceItemStatus.Delete, engine.TfsState.GetSourceItem(@"C:\Foo\Bar\Baz1\Fibble").LocalItemStatus);
                Assert.Equal(SourceItemStatus.Delete, engine.TfsState.GetSourceItem(@"C:\Foo\Bar\Baz1\hello.txt").LocalItemStatus);
                Assert.Equal(SourceItemStatus.Delete, engine.TfsState.GetSourceItem(@"C:\Foo\Bar\Baz2").LocalItemStatus);
                Assert.Equal(SourceItemStatus.Delete, engine.TfsState.GetSourceItem(@"C:\Foo\Bar\Baz3").LocalItemStatus);

                Assert.True(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar"));
                Assert.False(engine.FileSystem.FileExists(@"C:\Foo\Bar\biff.txt"));
                Assert.True(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar\Baz1"));
                Assert.True(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar\Baz1\Fibble"));
                Assert.False(engine.FileSystem.FileExists(@"C:\Foo\Bar\Baz1\hello.txt"));
                Assert.True(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar\Baz2"));
                Assert.True(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar\Baz3"));
            }

            [Fact]
            public void DeepNesting_ModifiedFile()
            {
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar\Baz1");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar\Baz2");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar\Baz3");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar\Baz1\Fibble");
                engine.FileSystem.WriteAllText(@"C:\Foo\Bar\biff.txt", "Biff!");
                engine.FileSystem.WriteAllText(@"C:\Foo\Bar\Baz1\hello.txt", "Hello...");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar", @"C:\Foo\Bar", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar/Baz1", @"C:\Foo\Bar\Baz1", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar/Baz2", @"C:\Foo\Bar\Baz2", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar/Baz3", @"C:\Foo\Bar\Baz3", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar/Baz1/Fibble", @"C:\Foo\Bar\Baz1\Fibble", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFile(@"C:\Foo\Bar\biff.txt", 1, 2, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFile(@"C:\Foo\Bar\Baz1\hello.txt", 3, 4, SourceItemStatus.Unmodified);
                engine.FileSystem.WriteAllText(@"C:\Foo\Bar\Baz1\hello.txt", "Goodbye...");

                engine.Delete(@"C:\Foo\Bar", false, null);

                Assert.Equal(SourceItemStatus.Unmodified, engine.TfsState.GetSourceItem(@"C:\Foo\Bar").LocalItemStatus);
                Assert.Equal(SourceItemStatus.Unmodified, engine.TfsState.GetSourceItem(@"C:\Foo\Bar\Baz1").LocalItemStatus);
                Assert.Equal(SourceItemStatus.Delete, engine.TfsState.GetSourceItem(@"C:\Foo\Bar\Baz1\Fibble").LocalItemStatus);
                Assert.Equal(SourceItemStatus.Modified, engine.TfsState.GetSourceItem(@"C:\Foo\Bar\Baz1\hello.txt").LocalItemStatus);
                Assert.Equal(SourceItemStatus.Delete, engine.TfsState.GetSourceItem(@"C:\Foo\Bar\Baz2").LocalItemStatus);
                Assert.Equal(SourceItemStatus.Delete, engine.TfsState.GetSourceItem(@"C:\Foo\Bar\Baz3").LocalItemStatus);
                Assert.Equal(SourceItemStatus.Delete, engine.TfsState.GetSourceItem(@"C:\Foo\Bar\biff.txt").LocalItemStatus);

                Assert.True(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar"));
                Assert.True(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar\Baz1"));
                Assert.True(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar\Baz2"));
                Assert.True(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar\Baz3"));
                Assert.True(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar\Baz1\Fibble"));
                Assert.False(engine.FileSystem.FileExists(@"C:\Foo\Bar\biff.txt"));
                Assert.True(engine.FileSystem.FileExists(@"C:\Foo\Bar\Baz1\hello.txt"));
            }

            [Fact]
            public void DeepNesting_ModifiedFile_Forced()
            {
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar\Baz1");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar\Baz2");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar\Baz3");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar\Baz1\Fibble");
                engine.FileSystem.WriteAllText(@"C:\Foo\Bar\biff.txt", "Biff!");
                engine.FileSystem.WriteAllText(@"C:\Foo\Bar\Baz1\hello.txt", "Hello...");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar", @"C:\Foo\Bar", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar/Baz1", @"C:\Foo\Bar\Baz1", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar/Baz2", @"C:\Foo\Bar\Baz2", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar/Baz3", @"C:\Foo\Bar\Baz3", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar/Baz1/Fibble", @"C:\Foo\Bar\Baz1\Fibble", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFile(@"C:\Foo\Bar\biff.txt", 1, 2, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFile(@"C:\Foo\Bar\Baz1\hello.txt", 3, 4, SourceItemStatus.Unmodified);
                engine.FileSystem.WriteAllText(@"C:\Foo\Bar\Baz1\hello.txt", "Goodbye...");

                engine.Delete(@"C:\Foo\Bar", true, null);

                Assert.Equal(SourceItemStatus.Delete, engine.TfsState.GetSourceItem(@"C:\Foo\Bar").LocalItemStatus);
                Assert.Equal(SourceItemStatus.Delete, engine.TfsState.GetSourceItem(@"C:\Foo\Bar\Baz1").LocalItemStatus);
                Assert.Equal(SourceItemStatus.Delete, engine.TfsState.GetSourceItem(@"C:\Foo\Bar\Baz1\Fibble").LocalItemStatus);
                Assert.Equal(SourceItemStatus.Delete, engine.TfsState.GetSourceItem(@"C:\Foo\Bar\Baz1\hello.txt").LocalItemStatus);
                Assert.Equal(SourceItemStatus.Delete, engine.TfsState.GetSourceItem(@"C:\Foo\Bar\Baz2").LocalItemStatus);
                Assert.Equal(SourceItemStatus.Delete, engine.TfsState.GetSourceItem(@"C:\Foo\Bar\Baz3").LocalItemStatus);
                Assert.Equal(SourceItemStatus.Delete, engine.TfsState.GetSourceItem(@"C:\Foo\Bar\biff.txt").LocalItemStatus);

                Assert.True(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar"));
                Assert.True(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar\Baz1"));
                Assert.True(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar\Baz2"));
                Assert.True(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar\Baz3"));
                Assert.True(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar\Baz1\Fibble"));
                Assert.False(engine.FileSystem.FileExists(@"C:\Foo\Bar\biff.txt"));
                Assert.False(engine.FileSystem.FileExists(@"C:\Foo\Bar\Baz1\hello.txt"));
            }

            [Fact]
            public void NestedAddedFile()
            {
                List<SourceItemCallbackData> results = new List<SourceItemCallbackData>();
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar");
                engine.FileSystem.WriteAllText(@"C:\Foo\Bar\biff.txt", "Biff!");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar", @"C:\Foo\Bar", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFile(@"C:\Foo\Bar\biff.txt", 1, 2, SourceItemStatus.Add);

                engine.Delete(@"C:\Foo\Bar", false, delegate(SourceItem i,
                                                             SourceItemResult r)
                                                    {
                                                        results.Add(new SourceItemCallbackData(i, r));
                                                    });

                Assert.Equal(2, results.Count);

                SourceItemCallbackData biff = results[0];
                Assert.Equal(@"C:\Foo\Bar\biff.txt", biff.SourceItem.LocalName);
                Assert.Equal(SourceItemResult.E_HasLocalModifications, biff.SourceItemResult);
                Assert.True(engine.FileSystem.FileExists(@"C:\Foo\Bar\biff.txt"));

                SourceItemCallbackData bar = results[1];
                Assert.Equal(@"C:\Foo\Bar", bar.SourceItem.LocalName);
                Assert.Equal(SourceItemResult.E_ChildDeleteFailure, bar.SourceItemResult);
                Assert.True(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar"));
            }

            [Fact]
            public void NestedAddedFile_Forced()
            {
                List<SourceItemCallbackData> results = new List<SourceItemCallbackData>();
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar");
                engine.FileSystem.WriteAllText(@"C:\Foo\Bar\biff.txt", "Biff!");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar", @"C:\Foo\Bar", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFile(@"C:\Foo\Bar\biff.txt", 1, 2, SourceItemStatus.Add);

                engine.Delete(@"C:\Foo\Bar", true, delegate(SourceItem i,
                                                            SourceItemResult r)
                                                   {
                                                       results.Add(new SourceItemCallbackData(i, r));
                                                   });

                Assert.Equal(2, results.Count);

                SourceItemCallbackData biff = results[0];
                Assert.Equal(@"C:\Foo\Bar\biff.txt", biff.SourceItem.LocalName);
                Assert.Equal(SourceItemResult.S_ForcedDelete, biff.SourceItemResult);
                Assert.False(engine.FileSystem.FileExists(@"C:\Foo\Bar\biff.txt"));
                Assert.False(engine.TfsState.IsFileTracked(@"C:\Foo\Bar\biff.txt"));

                SourceItemCallbackData bar = results[1];
                Assert.Equal(@"C:\Foo\Bar", bar.SourceItem.LocalName);
                Assert.Equal(SourceItemResult.S_Ok, bar.SourceItemResult);
                Assert.True(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar"));
                Assert.True(engine.TfsState.IsFolderTracked(@"C:\Foo\Bar"));
            }

            [Fact]
            public void NestedDeletedFolder()
            {
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar", @"C:\Foo\Bar", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar/Baz", @"C:\Foo\Bar\Baz", 0, 0, SourceItemStatus.Delete);

                engine.Delete(@"C:\Foo\Bar", true, null);

                Assert.Equal(SourceItemStatus.Delete, engine.TfsState.GetSourceItem(@"C:\Foo\Bar\Baz").LocalItemStatus);
            }

            [Fact]
            public void NestedFoldersNotTracked()
            {
                List<SourceItemCallbackData> results = new List<SourceItemCallbackData>();
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar\Baz");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar\Baz\Bob");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar/", @"C:\Foo\Bar", 0, 0, SourceItemStatus.Unmodified);

                engine.Delete(@"C:\Foo\Bar", false, delegate(SourceItem item,
                                                             SourceItemResult result)
                                                    {
                                                        results.Add(new SourceItemCallbackData(item, result));
                                                    });

                Assert.Equal(2, results.Count);

                SourceItemCallbackData baz = results[0];
                Assert.Equal(@"C:\Foo\Bar\Baz", baz.SourceItem.LocalName);
                Assert.Equal(SourceItemResult.E_NotUnderSourceControl, baz.SourceItemResult);

                SourceItemCallbackData bar = results[1];
                Assert.Equal(@"C:\Foo\Bar", bar.SourceItem.LocalName);
                Assert.Equal(SourceItemResult.E_ChildDeleteFailure, bar.SourceItemResult);
                Assert.Equal(SourceItemStatus.Unmodified, bar.SourceItem.LocalItemStatus);
                Assert.Equal(SourceItemStatus.Unmodified, engine.TfsState.GetSourceItem(@"C:\Foo\Bar").LocalItemStatus);
            }

            [Fact]
            public void NestedFoldersNotTracked_Forced()
            {
                List<SourceItemCallbackData> results = new List<SourceItemCallbackData>();
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar\Baz");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar\Baz\Bob");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar", @"C:\Foo\Bar", 0, 0, SourceItemStatus.Unmodified);

                engine.Delete(@"C:\Foo\Bar", true, delegate(SourceItem item,
                                                            SourceItemResult result)
                                                   {
                                                       results.Add(new SourceItemCallbackData(item, result));
                                                   });

                Assert.Equal(2, results.Count);

                SourceItemCallbackData baz = results[0];
                Assert.Equal(@"C:\Foo\Bar\Baz", baz.SourceItem.LocalName);
                Assert.Equal(SourceItemResult.S_ForcedDelete, baz.SourceItemResult);

                SourceItemCallbackData bar = results[1];
                Assert.Equal(@"C:\Foo\Bar", bar.SourceItem.LocalName);
                Assert.Equal(SourceItemResult.S_Ok, bar.SourceItemResult);
            }

            [Fact]
            public void NestedMissingFile()
            {
                List<SourceItemCallbackData> results = new List<SourceItemCallbackData>();
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar");
                engine.FileSystem.WriteAllText(@"C:\Foo\Bar\biff.txt", "Biff!");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar", @"C:\Foo\Bar", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFile(@"C:\Foo\Bar\biff.txt", 1, 2, SourceItemStatus.Unmodified);
                engine.FileSystem.DeleteFile(@"C:\Foo\Bar\biff.txt");

                engine.Delete(@"C:\Foo\Bar", false, delegate(SourceItem i,
                                                             SourceItemResult r)
                                                    {
                                                        results.Add(new SourceItemCallbackData(i, r));
                                                    });

                Assert.Equal(2, results.Count);

                SourceItemCallbackData biff = results[0];
                Assert.Equal(@"C:\Foo\Bar\biff.txt", biff.SourceItem.LocalName);
                Assert.Equal(SourceItemResult.S_Ok, biff.SourceItemResult);
                Assert.False(engine.FileSystem.FileExists(@"C:\Foo\Bar\biff.txt"));
                Assert.True(engine.TfsState.IsFileTracked(@"C:\Foo\Bar\biff.txt"));
                Assert.Equal(SourceItemStatus.Delete, engine.TfsState.GetSourceItem(@"C:\Foo\Bar\biff.txt").LocalItemStatus);

                SourceItemCallbackData bar = results[1];
                Assert.Equal(@"C:\Foo\Bar", bar.SourceItem.LocalName);
                Assert.Equal(SourceItemResult.S_Ok, bar.SourceItemResult);
                Assert.True(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar"));
                Assert.True(engine.TfsState.IsFolderTracked(@"C:\Foo\Bar"));
            }

            [Fact]
            public void NestedMissingFolder()
            {
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar\Baz");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar", @"C:\Foo\Bar", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar/Baz", @"C:\Foo\Bar\Baz", 0, 0, SourceItemStatus.Unmodified);
                engine.FileSystem.DeleteDirectory(@"C:\Foo\Bar\Baz", true);

                engine.Delete(@"C:\Foo\Bar", true, null);

                Assert.Equal(SourceItemStatus.Delete, engine.TfsState.GetSourceItem(@"C:\Foo\Bar\Baz").LocalItemStatus);
            }

            [Fact]
            public void NestedModifiedFile()
            {
                List<SourceItemCallbackData> results = new List<SourceItemCallbackData>();
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar");
                engine.FileSystem.WriteAllText(@"C:\Foo\Bar\biff.txt", "Biff!");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar", @"C:\Foo\Bar", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFile(@"C:\Foo\Bar\biff.txt", 1, 2, SourceItemStatus.Unmodified);
                engine.FileSystem.WriteAllText(@"C:\Foo\Bar\biff.txt", "Bob!");

                engine.Delete(@"C:\Foo\Bar", false, delegate(SourceItem i,
                                                             SourceItemResult r)
                                                    {
                                                        results.Add(new SourceItemCallbackData(i, r));
                                                    });

                Assert.Equal(2, results.Count);

                SourceItemCallbackData biff = results[0];
                Assert.Equal(@"C:\Foo\Bar\biff.txt", biff.SourceItem.LocalName);
                Assert.Equal(SourceItemResult.E_HasLocalModifications, biff.SourceItemResult);
                Assert.True(engine.FileSystem.FileExists(@"C:\Foo\Bar\biff.txt"));

                SourceItemCallbackData bar = results[1];
                Assert.Equal(@"C:\Foo\Bar", bar.SourceItem.LocalName);
                Assert.Equal(SourceItemResult.E_ChildDeleteFailure, bar.SourceItemResult);
                Assert.True(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar"));
            }

            [Fact]
            public void NestedModifiedFile_Forced()
            {
                List<SourceItemCallbackData> results = new List<SourceItemCallbackData>();
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar");
                engine.FileSystem.WriteAllText(@"C:\Foo\Bar\biff.txt", "Biff!");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar", @"C:\Foo\Bar", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFile(@"C:\Foo\Bar\biff.txt", 1, 2, SourceItemStatus.Unmodified);
                engine.FileSystem.WriteAllText(@"C:\Foo\Bar\biff.txt", "Bob!");

                engine.Delete(@"C:\Foo\Bar", true, delegate(SourceItem i,
                                                            SourceItemResult r)
                                                   {
                                                       results.Add(new SourceItemCallbackData(i, r));
                                                   });

                Assert.Equal(2, results.Count);

                SourceItemCallbackData biff = results[0];
                Assert.Equal(@"C:\Foo\Bar\biff.txt", biff.SourceItem.LocalName);
                Assert.Equal(SourceItemResult.S_ForcedDelete, biff.SourceItemResult);
                Assert.False(engine.FileSystem.FileExists(@"C:\Foo\Bar\biff.txt"));
                Assert.True(engine.TfsState.IsFileTracked(@"C:\Foo\Bar\biff.txt"));
                Assert.Equal(SourceItemStatus.Delete, engine.TfsState.GetSourceItem(@"C:\Foo\Bar\biff.txt").LocalItemStatus);

                SourceItemCallbackData bar = results[1];
                Assert.Equal(@"C:\Foo\Bar", bar.SourceItem.LocalName);
                Assert.Equal(SourceItemResult.S_Ok, bar.SourceItemResult);
                Assert.True(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar"));
                Assert.True(engine.TfsState.IsFolderTracked(@"C:\Foo\Bar"));
            }

            [Fact]
            public void NestedUnmodifiedFile()
            {
                TestableTfsEngine engine = TestableTfsEngine.Create();
                engine.FileSystem.EnsurePath(@"C:\Foo");
                engine.FileSystem.EnsurePath(@"C:\Foo\Bar");
                engine.FileSystem.WriteAllText(@"C:\Foo\Bar\biff.txt", "Biff!");
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/", @"C:\Foo", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFolder("http://tfsUrl", "$/ServerPath/Bar", @"C:\Foo\Bar", 0, 0, SourceItemStatus.Unmodified);
                engine.TfsState.TrackFile(@"C:\Foo\Bar\biff.txt", 1, 2, SourceItemStatus.Unmodified);

                engine.Delete(@"C:\Foo\Bar", false, null);

                SourceItem directoryItem = engine.TfsState.GetSourceItem(@"C:\Foo\Bar");
                Assert.Equal(SourceItemStatus.Delete, directoryItem.LocalItemStatus);
                Assert.True(engine.FileSystem.DirectoryExists(@"C:\Foo\Bar"));

                SourceItem fileItem = engine.TfsState.GetSourceItem(@"C:\Foo\Bar\biff.txt");
                Assert.Equal(SourceItemStatus.Delete, fileItem.LocalItemStatus);
                Assert.False(engine.FileSystem.FileExists(@"C:\Foo\Bar\biff.txt"));
            }
        }
    }
}